package org.journal.dao;

import java.io.Serializable;
import java.util.List;

import org.hibernate.LockMode;
import org.hibernate.LockOptions;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

@Repository
public class GenericDAOImpl<T, ID extends Serializable> implements
		GenericDAO<T, ID> {

	private final static Logger log = LoggerFactory
			.getLogger(GenericDAOImpl.class);

	@Autowired
	protected SessionFactory sessionFactory;

	@SuppressWarnings("unchecked")
	public T getEntityById(Class<T> type, Serializable id) {

		return (T) sessionFactory.getCurrentSession().get(type, id,
				new LockOptions(LockMode.PESSIMISTIC_WRITE));

	}

	public Serializable save(T entity) {

		return sessionFactory.getCurrentSession().save(entity);

	}

	public void merge(T entity) {

		sessionFactory.getCurrentSession().merge(entity);

	}

	public void update(T entity) {

		sessionFactory.getCurrentSession().update(entity);

	}

	public boolean remove(T entity) {
		sessionFactory.getCurrentSession().delete(entity);
		return false;
	}

	@SuppressWarnings("unchecked")
	public List<T> findAll(Class<T> clazz) {
		Query query = sessionFactory.getCurrentSession().createQuery(
				"Select entity from " + clazz.getCanonicalName() + " entity");

		return query.list();

	}

	@SuppressWarnings("unchecked")
	public List<T> search(Query query) {

		List<T> result = query.list();
		if (!result.isEmpty()) {
			log.debug("Search success result = {}", result);
			return result;
		}
		return null;

	}

	@SuppressWarnings("unchecked")
	public T searchUnique(Query query) {
		T result = (T) query.uniqueResult();
		log.debug("SearchUnique result = {}", result);
		return result;
	}

}
